Podejście obiektowe w tworzeniu aplikacji web
Opublikowano: 2009-07-28 , wyświetlono: 14407
Wstęp
Tekst ten ma na celu przedstawićenie pewnego sposobu podejścia do tworzenia aplikacji web z wykorzystaniem języka Perl i bazy danych MySql. Może być też przykładem praktycznego wykorzystania obiektowości w Perl'u. Całość tekstu oparta będzie na tworzeniu rozwiązania konkretnego, prostego problemu.
Zadanie:
Stworzyć małą aplikację, która ma wyświetlić cennik produktów w przeglądarce internetowej. Produkt będzie posiadał charaktryzował się czterema cechami:
id - unikalny identyfikator
kod - kod produktu
nazwa - nazwa produktu
cena - cena
Dane o produktach będą przechowywane będą w bazie MySql o nazwie test_oop w tabeli produkt.
Analiza problemu wskazuje, że potrzebne będą następujące klasy:
- klasa reprezentująca produkt
- klasa dostępu do bazy danych
- klasa odpowiadająca za odczyt produktów z tabeli
- klasa realizująca wyświetlanie cennika jako strony html
Pierwszym i najprostszym zadaniem będzie implementacja klasy produkt. Jej zadaniem będzie tylko reprezentacja atrybutów produktów.
id - unikalny identyfikator
kod - kod produktu
nazwa - nazwa produktu
cena - cena
Dane o produktach będą przechowywane będą w bazie MySql o nazwie test_oop w tabeli produkt.
Analiza problemu wskazuje, że potrzebne będą następujące klasy:
- klasa reprezentująca produkt
- klasa dostępu do bazy danych
- klasa odpowiadająca za odczyt produktów z tabeli
- klasa realizująca wyświetlanie cennika jako strony html
Pierwszym i najprostszym zadaniem będzie implementacja klasy produkt. Jej zadaniem będzie tylko reprezentacja atrybutów produktów.
package Produkt;
sub new
{
my $self = {};
$self->10 = 0;
$self->{kod} = "";
$self->{nazwa} = "";
$self->{cena} = 0.0;
bless ($self);
return $self;
}
return 1;
Następnym krokiem będzie stworzenie klasy do łączności z bazą danych MySql. Klasa będzie miała za zadanie nawiązać łączność z bazą oraz w wypadku powodzenia zwracać uchwyt do połączenia.
W związku z tym klasa zawierać będzie tylko konstruktor, w którym przekazane zostaną parametry połaczenia, czyli nazwa hosta, nazwa użytkownika, hasło, itp. Potrzebna będzie też metoda, która dokona połączenia i zwróci uchwyt do bazy danych, by wykorzystać go w klasach dostępu do konkretnych tabel. Poniżej implementacja klasy Database.
W związku z tym klasa zawierać będzie tylko konstruktor, w którym przekazane zostaną parametry połaczenia, czyli nazwa hosta, nazwa użytkownika, hasło, itp. Potrzebna będzie też metoda, która dokona połączenia i zwróci uchwyt do bazy danych, by wykorzystać go w klasach dostępu do konkretnych tabel. Poniżej implementacja klasy Database.
package Database;
# zmienna przechowujaca uchwyt do polaczenia
my $connection;
my $dbName;
my $dbUser;
my $dbPass;
my $dbHost;
my $dbPort;
sub new
{
my $class = shift;
my $self = {};
$dbName = shift;
$dbUser = shift;
$dbPass = shift;
$dbHost = shift;
$dbPort = shift;
if (!$dbPort)
{
$dbPort = 3306;
}
if (!$dbHost)
{
$dbHost = "localhost";
}
bless ($self, $class);
return $self;
}
# polaczenie z baza danych
#----------------------------------------------------------
sub Connect
{
my $self = shift;
$connection = DBI->connect("DBI:mysql:$dbName:$dbHost:$dbPort",
$dbUser, $dbPass)
|| return undef;
return $connection;
}
Mając klasę do nawiązania połączenia z bazą danych można rozpocząć projektowanie klasy dostępu do tabeli produkt, którą nazwiemy DbProdukt. Ma ona umożliwiać dodawanie, aktualizację oraz usunięcie wiersza na podstawie obiektu produkt. Operacje te powinny być łatwe w użyciu i czytelne w kodzie aplikacji. Konieczna też będzie metoda, która pozwala na przekazanie połączenia do bazy danych do tworzonej klasy.
# utworzenie obiektu polaczenia z baza
my $db = new Database("test_oop", "user", "pass", "host", "port");
my $conn = $db->Connect();
# utworzenie obiektu produkt
my $produkt = new Produkt();
# i ustawienie dla niego atrybutow
$produkt->10 = 0;
$produkt->{kod} = "0001";
$produkt->{nazwa} = "nasz produkt";
$produkt->{cena} = 10.50;
# utworzeni obiektu dostepu do tabeli produkt
my $dbProdukt = new DbProdukt($conn);
# dodanie takich samych kilku wierszy
$dbProdukt->Insert($produkt); # nadane id = 1
$dbProdukt->Insert($produkt); # nadane id = 2
$dbProdukt->Insert($produkt); # nadane id = 3
$dbProdukt->Insert($produkt); # nadane id = 4
Poniewaz pole id ma atrybut AUTOINCREMENT i jest to unikalny klucz, metody aktualizacji i usuwania powinny to wykorzystywac.
# aktualizacji ostatnio dodanego wiersza
$produkt->10 = 4;
$produkt->{kod} = "0004";
$produkt->{nazwa} = "zaktualizowana nazwa";
$produkt->{cena} = 12.30;
$dbProdukt->Update($produkt)
Ten sam sposób zostanie wykorzystany do usunięcia wiersza z tabeli.
# usuniecia wiersza o id = 2
$produkt->10 = 2;
$dbProdukt->Delete($produkt)
Jak do tej pory zastosowanie stworzonych klas jest bardzo proste i czytelne i implementacja nie powinna nastręczaj dużych trudności. Teraz pora na nieco trudniejsze zadanie. Niezbędny jest sposób czytania danych z wiersza tabeli, który utrzymany będzie w duchu dotychczasowych konstrukcji.
Można by spróbować w tradycyjny sposób, czyli:
Można by spróbować w tradycyjny sposób, czyli:
$rs = $conn->execute("SELECT * FROM produkt");
while ($row = $rs->fetchrow_hashref)
{
$produkt->10 = $row->10;
$produkt->{kod} = $row->{kod};
$produkt->{nazwa} = $row->{nazwa};
$produkt->{cena} = $row->{cena};
}
lecz nie wygląda to zbyt elegancko. Użyteczne byłoby pozbycie się zmiennych $rs i $row,
by ukryć funkcje z pakietu DBI. Spróbujmy w ten sposób:
by ukryć funkcje z pakietu DBI. Spróbujmy w ten sposób:
$dbProdukt->CreateQuery();
while ($produkt = $dbProdukt->GetRow())
{
print $produkt->{nazwa} . "\n";
}
Wygląda to zdecydowanie lepiej. Przydało by się jeszcze przy tworzeniu zapytania uwzględnienie przynajmniej klauzu WHERE i ORDER BY by mieć większy wpływ na otrzymywane wyniki.
# zapytanie SQL: SELECT * FROM produkt WHERE id > 1 ORDER BY nazwa
$dbProdukt->CreateQuery("id > 1", "nazwa");
# gdy GetRow() zwróci undef to znak, że odczytano wszystkie wiersze
while ($produkt = $dbProdukt->GetRow())
{
print $produkt->{nazwa} . "\n";
}
Taki dostęp do wierszy tabeli powinien już nas zadowolić.
Pozostała teraz część wizualna aplikacji, czyli zaprojektowanie klasy, która będzie odpowiadać za prezentację cennika. W tym momencie można przdstawić już zarys całej aplikacji.
Pozostała teraz część wizualna aplikacji, czyli zaprojektowanie klasy, która będzie odpowiadać za prezentację cennika. W tym momencie można przdstawić już zarys całej aplikacji.
use DBI;
use Cgi;
use Database;
use Produkt;
use HtmlProdukt;
$cgi = new Cgi();
my $db = new Database("test_oop", "root", "");
my $conn = $db->Connect();
$html = new HtmlProdukt($conn, $cgi);
$html->Head();
$html->PriceList();
$html->Foot();
exit;
Klasa HtmlProdukt będzie odpowiadać za odczyt parametrów przekazywanych w formularzach, czytanie danych z bazy i wyświetlanie wyników. W kodzie powyżej można zauważyć, że do klasy HtmlProdukt przekazane zaostało połączenie do bazy danych oraz obiekt CGI by można było operować na zmiennych przekazywanych z formularzy www.
Poniżej przedstawiona jest implementacja konstruktora.
Poniżej przedstawiona jest implementacja konstruktora.
package HtmlProdukt;
my $connDb;
my $queryCgi;
sub new
{
my $class = shift;
my $self = {};
$connDb = shift;
$queryCgi = shift;
bless ($self, $class);
return $self;
}
Główną metodą klasy jest PriceList(), która ma wyświetlić nasz cennik. Sposób wyświetlania będzie bardzo surowy, lecz wystarczający dla celow przykładu.
sub PriceList
{
$self = shift;
my $produkt = new Produkt();
my $dbProdukt = new DbProdukt($connDb);
print "\n";
$dbProdukt->CreateQuery(undef, "nazwa");
while ($produkt = $dbProdukt->GetRow())
{
print $produkt->{kod} . " ";
print $produkt->{nazwa} . " ";
print $produkt->{cena} . "\n";
}
print "\n";
}
I to już wszystko. Zadanie zostało wykonane.
Mam nadzieję, że ten sposób podejścia do pisania aplikecji web z wykorzystaniem Perl'a i MySql'a spowoduję większą czytelność i łatwiejsze modyfikowanie pisanych aplikacji.
Całość kodu źródowego dostępna jest w sekcji Download.
Data: 24-04-2004
Mam nadzieję, że ten sposób podejścia do pisania aplikecji web z wykorzystaniem Perl'a i MySql'a spowoduję większą czytelność i łatwiejsze modyfikowanie pisanych aplikacji.
Całość kodu źródowego dostępna jest w sekcji Download.
Data: 24-04-2004